home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-03-21 | 28.4 KB | 1,340 lines |
- Newsgroups: comp.sources.misc
- From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
- Subject: v06i075: cpic --- yet another troff preprocessor
- Reply-To: tcjones@watdragon.waterloo.edu (speedboat jones)
- Distribution: world
- Organization: U. of Waterloo, Ontario
-
- Posting-number: Volume 6, Issue 75
- Submitted-by: tcjones@watdragon.waterloo.edu (speedboat jones)
- Archive-name: cpic
-
-
-
- cpic --- troff preprocessor producing pic(1) output to draw some simple graphs
- and diagrams.
-
-
- This is a little language that lets you draw simple graphs (the nodes
- and edges type) in pic. There's very little to it and it produces nice
- pictures. The best way to see what happens is to make it and run the
- Example file through cpic and pic and eqn and troff -ms and compare what
- comes out to what went in. Good luck.
-
- Terry Jones
-
- Department Of Computer Science, University Of Waterloo
- Waterloo Ontario Canada N2L 3G1. Phone: 1-519-8884674
- UUCP: ...!watmath!watdragon!tcjones
- CSNET, Internet, CDNnet: tcjones@dragon.waterloo.{cdn,edu}
- BITNET: tcjones@WATER.bitnet
- Canadian domain: tcjones@dragon.uwaterloo.ca
-
-
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 1 (of 1)."
- # Contents: cpic cpic/Example cpic/README cpic/cpic.c cpic/cpic.h
- # Wrapped by tcjones@watdragon on Wed Mar 15 14:03:58 1989
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test ! -d 'cpic' ; then
- echo shar: Creating directory \"'cpic'\"
- mkdir 'cpic'
- fi
- if test -f 'cpic/Example' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'cpic/Example'\"
- else
- echo shar: Extracting \"'cpic/Example'\" \(4965 characters\)
- sed "s/^X//" >'cpic/Example' <<'END_OF_FILE'
- X.LP
- X.EQ
- delim $$
- X.EN
- X
- X.TL
- CPIC
- X
- X.NH 1
- Pictures vs Figures
- X
- X.PP
- XFor the purposes of this discussion a picture will be thought of as containing
- some positive number of figures. The figures are drawn side by side.
- X
- X.NH 1
- Delimiters and Arguments
- X
- X.PP
- Delimit the picture with .CPS and .CPE (Charlie Pic Start/End). The
- X\&.CPS line can take two real arguments, they are the radius of the
- circle on which the vertices of the figures are put, and the radius of
- the actual vertices. If only one argument is given it is taken as the
- radius of the figures. You can change the default values to suit
- yourself by doing obvious things to cpic.h. The default values are 0.4
- for the figure radius and 0.02 for the vertex radius.
- X
- X.NH 1
- How Many Figures to a Picture
- X
- X.PP
- You can have as many as you like (in theory). You will need to adjust
- the default figure radius if you require alot of figures or if you have
- wide labels on your figures.
- The first number after the .CPS line tells how many individual figures
- there will be in this picture.
- X
- X.NH 1
- Defining a Figure
- X
- X.PP
- XEach figure in the picture is specified as follows:
- firstly, give the number of vertices that will be in this figure,
- and then give its edge list.
- X
- X.NH 2
- The Figure's Vertex Count
- X
- X.PP
- Typically you will just want to simply say how many vertices are to be in the
- next figure of this picture. This is done as one would expect, by giving the
- count alone on a line. It is also possible to define a label for each figure.
- The label should be given enclosed in double quotes (") and will be placed to
- the left of the figure in question. Cpic will make a primitive attempt to
- estimate the width of the label. If the spacing is not correct the the width
- may also be given as a third parameter.
- X
- An example is
- X.br
- X8 "Octahedron" 1.0
- X.br
- which specifies a figure on eight vertices, labelled with the string
- X"Octahedron" centred in a field one inch wide. Cpic should be able to
- guesstimate the appropriate width for simple labels such as this.
- X
- X.NH 2
- A Figure's Edge List
- X
- X.PP
- XEdges are specified as a b c, meaning vertex a should be joined
- to vertex b with a multiplicity of c. If c is omitted it defaults to 1.
- c must be less than or equal to 3. The edge list should immediately
- follow the vertex count.
- X
- The vertices will be numbered from 1 upwards. Vertex 1 will always be
- located on the same horizontal level as the centre of the figure, and
- to the right of the centre. The numbering continues consecutively
- anti-clockwise around the circumference. I should have added a feature
- to allow for an initial rotation instead of insisting that the first
- vertex be at 0 degrees. This numbering is internal and should not be confused
- with labels that might one day appear on vertices when the page is printed.
- X
- X.NH 1
- Labelling the Entire Picture
- X
- X.PP
- This is most comfortably accomplished by giving the label after the .CPE.
- X
- X.NH 1
- Comments etc.
- X
- X.PP
- Comments are allowed - a comment line is one that starts with a #.
- Blank lines are also ignored. The entire cpic specification will be
- output (commented out) within the produced pic.
- X
- X
- X.NH 1
- Invocation
- X
- X.PP
- Cpic can be run as a filter or may take file name arguments (but not
- both simultaneously). Output may be sent to a file or (by default) to stdout.
- Use -o <filename> to write output to a file. This will not overwrite an
- existing file though, for that use -O <filename>.
- The input specification will be given (commented) in the output pic.
- X.br
- The following are valid.
- X
- X.br
- X.I
- cpic fred.in > fred.out
- X.br
- cpic -o fred.out fred.in
- X.br
- cat fred.in | cpic > fred.out
- X.br
- cat fred.in | cpic | pic | tbl etc etc etc...
- X.br
- X.R
- X
- X.NH 1
- Notes
- X
- X.PP
- All measurements should be given in inches and as floating point
- numbers, there is no need to specify the trailing "i" for inches \- the
- world will probably end if you do. The generated pic could be tidied
- considerably, and I should add the ability to label vertices and an
- option to give an initial rotation for each figure. Let me know if you
- want any of this done.
- X
- X.NH 1
- XExample
- X
- X.PP
- You get the idea. Here is an example.
- X
- X.CPS 0.3
- X# use figure radius of 0.3 inches.
- X
- X# six figures in this diagram (six things on this line).
- X6
- X
- X# the first has 4 vertices.
- X4 "A:"
- X1 2 3
- X2 3 2
- X3 4
- X
- X# one with 16 vertices...
- X16 "B:"
- X2 3 2
- X4 7 1
- X8 11 3
- X5 9
- X1 7
- X4 12
- X13 14
- X
- X# the third.
- X5 "C:"
- X1 3
- X3 5
- X5 2
- X2 4
- X4 1
- X
- X# the fourth.
- X2 "D:"
- X1 2 3
- X
- X# the fifth.
- X8 "E:"
- X1 2 2
- X2 3
- X5 2 3
- X6 1 1
- X2 4 2
- X3 4
- X4 5 2
- X5 6 2
- X6 7
- X7 8
- X
- X# the sixth.
- X6 "F:"
- X1 2 1
- X4 5 2
- X5 6 3
- X.CPE
- X
- X.ce
- XFig 3: Six pretty little figures are shown above.
- X
- X
- X
- The vortex...
- X
- X.CPS
- X1
- X16 "$ sigma pi 2x sub i$" 1.0
- X# tell cpic how long the label is as it doesn't understand eqn.
- X
- X1 8
- X8 15
- X15 6
- X6 13
- X13 4
- X4 11
- X11 2
- X2 9
- X9 16
- X16 7
- X7 14
- X14 5
- X5 12
- X12 3
- X3 10
- X10 1
- X.CPE
- X.ce
- XFig 900: The vortex.
- X
- X.PP
- Here are some that are not in the default size.
- X.CPS 0.5 .05
- X3
- X
- X3 "Three pictures:"
- X2 3 2
- X2 1 2
- X
- X3
- X1 2 2
- X1 3 2
- X
- X3
- X3 1 2
- X3 2 2
- X.CPE
- X.ce
- Three lovely little babies.
- X
- X.br
- Goodbye
- END_OF_FILE
- if test 4965 -ne `wc -c <'cpic/Example'`; then
- echo shar: \"'cpic/Example'\" unpacked with wrong size!
- fi
- # end of 'cpic/Example'
- fi
- if test -f 'cpic/README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'cpic/README'\"
- else
- echo shar: Extracting \"'cpic/README'\" \(788 characters\)
- sed "s/^X//" >'cpic/README' <<'END_OF_FILE'
- X
- cpic --- troff preprocessor producing pic(1) output to draw some simple graphs
- X and diagrams.
- X
- X
- This is a little language that lets you draw simple graphs (the nodes and
- edges type) in pic. There's very little to it and it produces nice
- pictures. The best way to see what happens is to compile it and
- run the Example file through cpic and then pic and eqn and troff -ms and
- have a look at what comes out. Good luck.
- X
- Terry Jones
- X
- X Department Of Computer Science, University Of Waterloo
- X Waterloo Ontario Canada N2L 3G1. Phone: 1-519-8884674
- X UUCP: ...!watmath!watdragon!tcjones
- X CSNET, Internet, CDNnet: tcjones@dragon.waterloo.{cdn,edu}
- X BITNET: tcjones@WATER.bitnet
- X Canadian domain: tcjones@dragon.uwaterloo.ca
- END_OF_FILE
- if test 788 -ne `wc -c <'cpic/README'`; then
- echo shar: \"'cpic/README'\" unpacked with wrong size!
- fi
- # end of 'cpic/README'
- fi
- if test -f 'cpic/cpic.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'cpic/cpic.c'\"
- else
- echo shar: Extracting \"'cpic/cpic.c'\" \(17631 characters\)
- sed "s/^X//" >'cpic/cpic.c' <<'END_OF_FILE'
- X/*
- X * Cpic.c --- produce pic output for graphs in which all vertices lie on a
- X * circle and edge multiplicity is <= 3.
- X *
- X * Terry Jones (tcjones@watdragon)
- X */
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <errno.h>
- X#include <signal.h>
- X#include <math.h>
- X#include "cpic.h"
- X
- char *this_file;
- XFILE *in_fp;
- XFILE *out_fp;
- char *myname;
- int line_number = 0;
- int found_line = 0;
- edge_list *avail_edges = NULL;
- picture *avail_pics = NULL;
- X
- main(argc, argv)
- int argc;
- char **argv;
- X{
- X extern char *getenv();
- X FILE *open_file();
- X extern void clean_up();
- X int std_in = 0;
- X
- X myname=*argv;
- X handle_signals();
- X
- X set_io(argv, &argc, &std_in);
- X
- X if (std_in){
- X in_fp = stdin;
- X this_file = "(standard input)";
- X do_file(stdin, out_fp);
- X }
- X else{
- X if (out_fp != stdout){
- X argc -= 2;
- X argv += 2;
- X }
- X while (--argc){
- X this_file = *++argv;
- X in_fp = open_file(this_file,"r",0);
- X if (in_fp == NULL) continue;
- X do_file(in_fp, out_fp);
- X }
- X }
- X fclose(out_fp);
- X exit(0);
- X}
- X
- X
- set_io(c, n, std_in)
- char **c;
- int *n;
- int *std_in;
- X{
- X switch (*n - 1){
- X
- X case 0: {
- X *std_in = 1;
- X out_fp = stdout;
- X break;
- X }
- X
- X case 1: {
- X if (!strcmp(c[1],"-h") || !strcmp(c[1],"-help")) help();
- X out_fp = stdout;
- X break;
- X }
- X
- X default: {
- X if (!strcmp(c[1],"-o")){
- X out_fp = open_file(c[2], "w", 0); /* open w/o clobbering. */
- X
- X if (*n == 3){
- X *std_in = 1;
- X }
- X }
- X
- X else if (!strcmp(c[1],"-O")){
- X out_fp = open_file(c[2], "w", 1); /* open & clobber. */
- X
- X if (*n == 3){
- X *std_in = 1; /* All arguments are used up. */
- X }
- X }
- X
- X else out_fp = stdout;
- X break;
- X }
- X }
- X}
- X
- X
- help()
- X{
- X fprintf(stderr,"Usage: %s [-[oO] outfile] [infiles...]\n", myname);
- X exit(0);
- X}
- X
- X
- handle_signals()
- X{
- X if (signal(SIGINT,SIG_IGN)!=SIG_IGN){
- X signal(SIGINT,clean_up);
- X }
- X}
- X
- void
- clean_up()
- X{
- X fprintf(stderr,"\nInterrupt...\n");
- X goodbye();
- X}
- X
- do_file(in_f, out_f)
- XFILE *in_f;
- XFILE *out_f;
- X{
- X extern picture *begin_picture();
- X extern char *get_quoted_name();
- X char *getline();
- X char line[MAX];
- X picture_list pics;
- X picture *curr_pic = NULL;
- X char *pic_title = NULL;
- X int pics_this_list = 0;
- X double picr;
- X double ptr;
- X
- X pics.pic = NULL;
- X
- X while ( GETLINE ){
- X
- X line_number++;
- X
- X /* A line we are not interested in, print it and go on. */
- X if (strlen(line) < 4 || strncmp(line, ".CPS", 4) != 0){
- X fprintf(out_f, "%s\n", line);
- X continue;
- X }
- X
- X
- X /* A line we are interested in. */
- X /* This line will have format ".CPS [pic_radius] [point_radius]" */
- X
- X switch (sscanf(line,".CPS %f %f", &picr, &ptr)){
- X
- X case EOF: {
- X /* Could not match, but tried. */
- X picr = PIC_RADIUS;
- X ptr = POINT_RADIUS;
- X break;
- X }
- X
- X case 1: {
- X /* Got picr from the sscanf */
- X ptr = POINT_RADIUS;
- X break;
- X }
- X
- X case 2: {
- X break;
- X }
- X
- X default: {
- X fprintf(stderr,
- X "%s: .CPS line syntax is \".CPS [picture radius [", myname);
- X fprintf(stderr,
- X "point radius]]\". Both are taken to be in inches and\n");
- X fprintf(stderr,
- X "default to %.2f and %.2f if omitted. (Line=%d, File=%s)\n",
- X PIC_RADIUS, POINT_RADIUS, line_number, this_file);
- X
- X goodbye();
- X break;
- X }
- X
- X }
- X
- X /* Start pic processing. */
- X /* fprintf(out_f, ".PS\n#%s\n", line); */
- X fprintf(out_f, ".PS\n");
- X
- X
- X if ( ! GETLINE ) goodbye();
- X line_number++;
- X
- X while (allwhite(line) || iscomment(line)){
- X /* fprintf(out_f,"%s\n",line); */
- X if ( ! GETLINE ) goodbye();
- X line_number++;
- X }
- X
- X /* Get the number of pictures that will be on this line. */
- X if (sscanf(line, "%d", &pics_this_list) != 1) goodbye();
- X found_line = line_number;
- X
- X pic_title = get_quoted_name(line);
- X begin_picture_list(&pics, pics_this_list, pic_title);
- X
- X /* Used to print out the definition commented out, but don't worry. */
- X /* fprintf(out_f, "#%s\n", line); */
- X
- X while ( GETLINE ){
- X
- X int n1, n2, n3;
- X int pictures_done = 0;
- X
- X line_number++;
- X
- X /* skip blank and comment lines */
- X while (allwhite(line) || iscomment(line)){
- X /* fprintf(out_f,"%s\n", line); */
- X if ( ! GETLINE ) goodbye();
- X line_number++;
- X }
- X
- X /* Now we have a non-blank, non-comment line. */
- X /* Don't worry about echoing it. */
- X /* fprintf(out_f, "#%s\n", line); */
- X
- X switch(sscanf(line, "%d %d %d", &n1, &n2, &n3)){
- X
- X /* The number of vertices that this picture will be on. */
- X case 1: {
- X
- X extern char *get_quoted_name();
- X extern double get_width();
- X
- X double width = get_width(line);
- X char *pic_name = get_quoted_name(line);
- X
- X curr_pic =
- X begin_picture(&pics, curr_pic, n1, pic_name, width);
- X break;
- X }
- X
- X
- X /* Two vertices which are to be joined (once). */
- X case 2: {
- X add_edges(curr_pic, n1, n2, 1);
- X break;
- X }
- X
- X /* Two vertices to be joined and the edge multiplicity */
- X case 3: {
- X add_edges(curr_pic, n1, n2, n3);
- X break;
- X }
- X
- X default: {
- X if (strlen(line) < 4 || strncmp(line, ".CPE", 4) != 0){
- X fprintf(stderr,"Whoops! bad input \n");
- X
- X goodbye();
- X }
- X
- X end_picture(&pics, picr, ptr, out_f);
- X pictures_done = 1;
- X break;
- X }
- X }
- X
- X if (pictures_done) break;
- X }
- X }
- X fclose(in_f);
- X}
- X
- begin_picture_list(pl, max_vertices, pic_title)
- picture_list *pl;
- int max_vertices;
- char *pic_title;
- X{
- X if (pl->pic != NULL) free_picture_list(pl);
- X pl->pic_limit = max_vertices;
- X pl->pics_in_list = 0;
- X pl->total_label_width = 0.0;
- X strcpy(pl->pic_title, pic_title);
- X pl->pic = NULL;
- X}
- X
- X
- picture *
- begin_picture(pl, cp, vertices, pic_name, width)
- picture_list *pl;
- picture *cp;
- int vertices;
- char *pic_name;
- double width;
- X{
- X extern picture *new_picture();
- X
- X if (pl->pic_limit == pl->pics_in_list){
- X fprintf(stderr,"%s: %d pictures promised on line %d of file %s,\n",
- X myname, pl->pic_limit, found_line, this_file);
- X
- X fprintf(stderr,"but the picture beginning line %d exceeds this!\n",
- X line_number);
- X goodbye();
- X }
- X
- X if (vertices == 0){
- X fprintf(stderr,
- X "%s: A graph with 0 vertices? Interesting. Line=%d, File=%s.\n",
- X myname, line_number, this_file);
- X goodbye();
- X }
- X
- X if (width < 0.0){
- X fprintf(stderr,
- X "%s: A label with negative width? Interesting. Line=%d, File=%s.\n",
- X myname, line_number, this_file);
- X goodbye();
- X }
- X
- X
- X pl->pics_in_list++;
- X
- X if (pl->pic == NULL){
- X pl->pic = cp = new_picture();
- X }
- X else{
- X cp->next_pic = new_picture();
- X cp = cp->next_pic;
- X }
- X
- X
- X /* Try to estimate the label's width. */
- X /* Actual string to be printed does not include the 2 "'s */
- X if (pic_name && width == 0.0)
- X width = CHAR_WIDTH * (double)(strlen(pic_name) - 2);
- X
- X /* Add to the total amount of label space we have seen for this pic. */
- X if (pic_name)
- X pl->total_label_width += width;
- X
- X cp->vertices = vertices;
- X strcpy(cp->fig_name, pic_name);
- X cp->label_width = width;
- X return(cp);
- X}
- X
- X
- add_edges(cp, v1, v2, multiplicity)
- picture *cp;
- int v1;
- int v2;
- int multiplicity;
- X{
- X extern edge_list *new_edge_list();
- X edge_list *temp_e_list;
- X
- X if (cp == NULL){
- X fprintf(stderr,"%s: Oops! you tried to define edges before saying\n",
- X myname);
- X fprintf(stderr,
- X "how many vertices there were going to be. Line=%d, File=%s\n",
- X line_number, this_file);
- X goodbye();
- X }
- X
- X if (v1 < 1 || v2 < 1 || v1 > cp->vertices || v2 > cp->vertices){
- X fprintf(stderr,
- X "%s: Vertex index outside legal range on line %d, in file %s.\n",
- X myname, line_number, this_file);
- X goodbye();
- X }
- X
- X if (multiplicity < 1 || multiplicity > 3){
- X fprintf(stderr,
- X "%s: Illegal edge multiplicity of %d give on line %d in file %s.\n",
- X myname, multiplicity, line_number, this_file);
- X goodbye();
- X }
- X
- X if (v1 == v2){
- X fprintf(stderr,
- X"%s: Self loops not supported - edge %d,%d ignored on line %d in file %s.\n",
- X myname, v1, v1, line_number, this_file);
- X return;
- X }
- X
- X temp_e_list = new_edge_list();
- X
- X temp_e_list->v1 = v1;
- X temp_e_list->v2 = v2;
- X temp_e_list->times = multiplicity;
- X
- X temp_e_list->next_edge = cp->e_list;
- X cp->e_list = temp_e_list;
- X}
- X
- XFILE *
- open_file(s,mode,flag)
- char *s;
- char *mode;
- int flag;
- X{
- X /*
- X * fopen() the file whose name is "s", exit on error.
- X * flag is clobber mode for "w". 1 = clobber existing file.
- X *
- X */
- X
- X
- X FILE *fp, *fopen();
- X struct stat buf;
- X
- X if (strcmp(mode,"w") == 0 && flag != 1 && stat(s, &buf) != -1){
- X fprintf(stderr,
- X "%s: file \"%s\" already exists! (Use -O to overwrite.)\n",
- X myname, s);
- X exit(1);
- X }
- X
- X if (!(fp=fopen(s,mode))){
- X fprintf(stderr,"%s: could not open %s (ignored).\n", myname, s);
- X }
- X
- X return(fp);
- X}
- X
- X
- X
- int
- file_exists(s)
- char *s;
- X{
- X /*
- X * return 1 if the file s exists, 0 if not.
- X * This is silly - I should have used access(). Didn't know about it.
- X *
- X */
- X
- X
- X extern int errno;
- X struct stat buf;
- X int status;
- X
- X status = stat(s, &buf);
- X
- X if (status == 0){
- X return(1);
- X }
- X else if (status == -1 && errno == ENOENT){
- X return(0);
- X }
- X else{
- X fprintf(stderr,"file_exists: stat failed, errno=%d\n", errno);
- X perror("stat");
- X exit(1);
- X }
- X}
- X
- char *
- getline(fp,max,where)
- XFILE *fp;
- int max;
- char *where;
- X{
- X /* returns null terminated line in "where" and NULL on EOF or error */
- X /* essentially does what gets() does, except for any open FILE * */
- X
- X extern char* index();
- X char *fred;
- X
- X if ((fred=fgets(where,max,fp))){
- X char *tmp;
- X if (!(tmp=index(where,'\n'))){
- X printf("getline: Line with no newline!\n");
- X exit(1);
- X }
- X *tmp='\0';
- X }
- X return(fred);
- X}
- X
- X
- int
- allwhite(s)
- char *s;
- X{
- X /*
- X * Return 1 if the char array s is all white space, or empty.
- X *
- X */
- X
- X if (!strlen(s)) return(1);
- X
- X while (*s){
- X if (*s != ' ' && *s != '\t'){
- X return(0);
- X }
- X s++;
- X }
- X return(1);
- X}
- X
- X
- picture *
- new_picture()
- X{
- X picture *temp;
- X
- X if (avail_pics == NULL){
- X if ((temp = (picture *)malloc((unsigned long)sizeof(picture))) == NULL){
- X fprintf(stderr,"Could not malloc! giving up.\n");
- X exit(1);
- X }
- X }
- X else{
- X temp = avail_pics;
- X avail_pics = avail_pics->next_pic;
- X }
- X
- X temp->vertices = 0;
- X temp->fig_name[0] = '\0';
- X temp->label_width = 0.0;
- X temp->e_list = NULL;
- X temp->next_pic = NULL;
- X return(temp);
- X}
- X
- edge_list *
- new_edge_list()
- X{
- X edge_list *temp;
- X
- X if (avail_edges == NULL){
- X if ((temp =
- X (edge_list *)malloc((unsigned long)sizeof(edge_list))) == NULL){
- X
- X fprintf(stderr,"Could not malloc! giving up.\n");
- X exit(1);
- X }
- X }
- X else{
- X temp = avail_edges;
- X avail_edges = avail_edges->next_edge;
- X }
- X
- X temp->v1 = temp->v2 = temp->times = 0;
- X temp->next_edge = NULL;
- X return(temp);
- X}
- X
- goodbye()
- X{
- X fflush(stderr);
- X fclose(in_fp);
- X fclose(out_fp);
- X fprintf(stderr,"%s: Execution aborted on line %d in file %s.\n",
- X myname, line_number, this_file);
- X exit(1);
- X}
- X
- X
- X
- free_picture_list(pl)
- picture_list *pl;
- X/* This does not seem to free anything! Is it wrong? TERRY! */
- X{
- X picture *this_pic = pl->pic;
- X edge_list *this_e_list;
- X
- X if (this_pic == NULL) return;
- X
- X while (this_pic->next_pic != NULL){
- X if (this_pic->e_list != NULL){
- X this_e_list = this_pic->e_list;
- X while (this_e_list->next_edge != NULL){
- X this_e_list = this_e_list->next_edge;
- X }
- X
- X this_e_list->next_edge = avail_edges;
- X avail_edges = this_pic->e_list;
- X }
- X
- X this_pic = this_pic->next_pic;
- X }
- X this_pic->next_pic = avail_pics;
- X avail_pics = pl->pic;
- X}
- X
- X
- end_picture(pl, picr, ptr, f)
- picture_list *pl;
- double picr;
- double ptr;
- XFILE *f;
- X{
- X /* Produce pic output for each of the pictures in the picture list. */
- X
- X /*
- X * Will need to do some looking at the list to determine the width
- X * and other things like that - saving on recomputation of sins etc.
- X * but for now just be dumb so we can get some output!
- X */
- X
- X picture *p = pl->pic;
- X int rad_count = 1;
- X int sep_count = 1;
- X double sep;
- X double pic_y;
- X double arc_rad;
- X double x_adjust = BOUNDARY;
- X
- X if (pl->pic_limit != pl->pics_in_list){
- X fprintf(stderr,
- X "%s: You promised %d graphs but gave %d. (Line %d, File %s)\n",
- X myname, pl->pic_limit, pl->pics_in_list, line_number, this_file);
- X goodbye();
- X }
- X
- X /* Calculate inter-picture separator. */
- X sep = (PAGE_WIDTH -
- X (2.0 * (double)(pl->pic_limit) * picr) - pl->total_label_width
- X ) / (double)(pl->pic_limit + 1.0);
- X
- X /* Calculate height of figure centres. */
- X pic_y = picr + BOUNDARY + (pl->pic_title[0] ? TITLE_SEP : 0.0);
- X
- X /*
- X * debug - point of reference.
- X * fprintf(f,"circle rad 0.1i at (0i,%.2fi) #invisible\n", picr + sep);
- X */
- X
- X while (p != NULL){
- X /* process each picture in turn. */
- X
- X char centre[15];
- X
- X x_adjust += p->label_width; /* Will be 0.0 if there is no label. */
- X sprintf(centre,"(%.2fi,%.2fi)",
- X rad_count*picr + sep_count*sep + x_adjust, pic_y);
- X
- X produce_pic(p, centre, picr, ptr, f);
- X
- X rad_count += 2;
- X sep_count++;
- X p = p->next_pic;
- X }
- X
- X /*
- X * DISABLED - use .ce in plain troff to get the title for the picture
- X * Do the title for the whole picture.
- X * if (pl->pic_title[0]){
- X * fprintf(f, "%s at (%.2fi,%2fi)\n", pl->pic_title,
- X *
- X * either -- BOUNDARY + sep * (double)(pl->pic_limit + 1) / 2.0 +
- X * picr * 2.0 * (double)(pl->pic_limit) / 2.0,
- X * -- or -- PAGE_WIDTH / 2.0,
- X *
- X * TITLE_SEP);
- X * }
- X */
- X
- X fprintf(f,".PE\n");
- X}
- X
- X
- produce_pic(p, centre, picr, ptr, f)
- picture *p;
- char *centre;
- double picr;
- double ptr;
- XFILE *f;
- X{
- X extern double cos();
- X extern double sin();
- X
- X int i;
- X static int vertex_count = 0;
- X static point *points;
- X
- X /* See if there is any need to recompute the vertex coordinates. */
- X
- X if (p->vertices != vertex_count){
- X
- X double inc = 360.0 / (double) p->vertices; /* p->vertices != zero */
- X
- X /* Need more space than there is - free the old and calloc again. */
- X
- X if (p->vertices > vertex_count){
- X free(points);
- X if ((points =
- X (point *)calloc(p->vertices+1, sizeof(point))) == NULL){
- X fprintf(stderr,"%s: Could not calloc! Goodbye.\n",myname);
- X goodbye();
- X }
- X }
- X
- X vertex_count = p->vertices;
- X
- X for (i=1; i<=p->vertices; i++){
- X double fred = (double)(i-1) * inc * RAD_ADJ;
- X points[i].x = picr * cos( fred );
- X points[i].y = picr * sin( fred );
- X }
- X }
- X
- X plot_label(centre, picr, p->fig_name, p->label_width, f);
- X define_vertices(points, p->vertices, centre, ptr, f);
- X plot_vertices(p->vertices, f);
- X plot_edges(points, p->e_list, centre, f);
- X}
- X
- X
- plot_label(centre, picr, name, width, f)
- char *centre;
- double picr;
- char *name;
- double width;
- XFILE *f;
- X{
- X if (*name){
- X fprintf(f,"# Picture title.\n");
- X fprintf(f, "%s at %s - (%2fi, 0i)\n", name, centre,(width/2.0) + picr);
- X fprintf(f,"#\n");
- X }
- X}
- X
- X
- define_vertices(pts, n, centre, ptr, f)
- point *pts;
- int n;
- char *centre;
- double ptr;
- XFILE *f;
- X{
- X /*
- X * Output the defined positions of the vertices.
- X */
- X
- X register int i;
- X
- X fprintf(f,"# Vertice definitions.\n");
- X for (i=1; i<=n; i++){
- X fprintf(f,"define V_%d X (%.2f,%.2f) + %s X\n", i, pts[i].x, pts[i].y,
- X centre);
- X }
- X fprintf(f,"define Pt_Radius X %.2fi X\n", ptr);
- X fprintf(f,"#\n");
- X}
- X
- X
- plot_vertices(n, f)
- int n;
- XFILE *f;
- X{
- X int i;
- X
- X fprintf(f,"# Set default circle radius\n");
- X fprintf(f,"circlerad = Pt_Radius\n");
- X fprintf(f,"#\n");
- X
- X fprintf(f, "# Do the vertices.\n");
- X
- X for (i=1; i<=n; i++){
- X
- X /*
- X * This will produce labelled vertices from 1,2,...n - useful in debug.
- X * fprintf(f,"circle \"%d\" at V_%d\n", i, i);
- X */
- X
- X fprintf(f,"circle at V_%d\n", i);
- X }
- X fprintf(f,"#\n");
- X}
- X
- X
- plot_edges(pts, edges, centre, f)
- point *pts;
- edge_list *edges;
- char *centre;
- XFILE *f;
- X{
- X /* No need to check that vertex numbers are in range - done in add_edges. */
- X
- X extern double get_arc_radius();
- X extern double distance();
- X char arc_radius[15];
- X
- X fprintf(f,"# Draw the edges.\n");
- X
- X while (edges != NULL){
- X
- X int one = edges->v1;
- X int two = edges->v2;
- X
- X if (edges->times != 1){
- X fprintf(f,"arcrad = %.2f\n",
- X get_arc_radius(distance(pts[one].x, pts[one].y,
- X pts[two].x, pts[two].y)));
- X }
- X
- X /* No need to check multiplicities - done in add_edges. */
- X switch(edges->times){
- X
- X case 1: {
- X fprintf(f,"line from V_%d to V_%d\n", one, two);
- X break;
- X }
- X
- X case 2: {
- X fprintf(f,"arc from V_%d to V_%d\n", one, two);
- X fprintf(f,"arc from V_%d to V_%d\n", two, one);
- X break;
- X }
- X
- X case 3: {
- X
- X fprintf(f,"line from V_%d to V_%d\n", one, two);
- X fprintf(f,"arc from V_%d to V_%d\n", one, two);
- X fprintf(f,"arc from V_%d to V_%d\n", two, one);
- X break;
- X }
- X }
- X
- X edges = edges->next_edge;
- X }
- X fprintf(f,"#\n");
- X}
- X
- X
- double
- get_arc_radius(d)
- double d;
- X{
- X /*
- X * Some empirical arc radius values depending on the inter pt dist.
- X * IT'S PROBABLY NOT A GOOD IDEA TO FIDDLE WITH THESE...
- X * of course i should now use all the least squares stuff i learned
- X * for the comps :-)
- X */
- X
- X if (d < 0.2) return(0.15);
- X if (d < 0.3) return(0.32);
- X if (d < 0.35) return(0.45);
- X if (d < 0.4) return(0.6);
- X /*if (d < 0.45) return(0.65);*/
- X if (d < 0.5) return(0.8);
- X if (d < 0.6) return(1.05);
- X if (d < 0.7) return(1.22);
- X if (d < 0.77) return(1.32);
- X if (d < 0.85) return(1.75);
- X if (d < 1.0) return(2.0);
- X if (d < 1.5) return(2.5);
- X return(3.0);
- X}
- X
- X
- double
- distance(x1, why1, x2, y2)
- double x1;
- double why1;
- double x2;
- double y2;
- X{
- X return( sqrt ((x1-x2)*(x1-x2) + (why1-y2)*(why1-y2)) );
- X}
- X
- X
- char *
- get_quoted_name(s)
- char *s;
- X{
- X /*
- X * Try to find a quoted "" string in the array s. If one exists
- X * then return a pointer to the first quote, having zeroed the
- X * character after the closing quote.
- X */
- X
- X char *start = index(s, '"');
- X
- X if (start){
- X char *quotes = index(start + 1, '"');;
- X if (quotes == NULL){
- X fprintf(stderr, "Closing quote omitted on figure name. Line");
- X fprintf(stderr, " %d, file %s.\n", line_number, this_file);
- X goodbye();
- X }
- X *(quotes + 1) = '\0';
- X }
- X return(start);
- X}
- X
- X
- double
- get_width(s)
- char *s;
- X{
- X char *quote1, *quote2;
- X double w = 0.0;
- X
- X if ( (quote1 = index(s,'"')) == NULL ||
- X (quote2 = index(quote1 + 1, '"')) == NULL ||
- X sscanf(quote2 + 1, "%f", &w) != 1 )
- X
- X return(0.0);
- X
- X return(w);
- X}
- END_OF_FILE
- if test 17631 -ne `wc -c <'cpic/cpic.c'`; then
- echo shar: \"'cpic/cpic.c'\" unpacked with wrong size!
- fi
- # end of 'cpic/cpic.c'
- fi
- if test -f 'cpic/cpic.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'cpic/cpic.h'\"
- else
- echo shar: Extracting \"'cpic/cpic.h'\" \(949 characters\)
- sed "s/^X//" >'cpic/cpic.h' <<'END_OF_FILE'
- X/* cpic.h */
- X
- X#define POINT_RADIUS 0.02
- X#define PIC_RADIUS 0.4
- X#define PAGE_WIDTH 6.5
- X#define TITLE_SEP 0.25
- X#define BOUNDARY 0.2
- X#define CHAR_WIDTH 0.12
- X#define PIC_NAME_LIMIT 512
- X#define PIC_TITLE_LIMIT 512
- X
- X#define RAD_ADJ ( 3.14159265 / 180.0 )
- X#define MAX 1024
- X
- X#define GETLINE getline(in_f, MAX, line)
- X#define iscomment(s) (*s == '#')
- X
- X
- typedef struct {
- X double x;
- X double y;
- X} point;
- X
- typedef struct edge_list_entry {
- X int v1;
- X int v2;
- X int times;
- X struct edge_list_entry *next_edge;
- X} edge_list;
- X
- typedef struct pict {
- X int vertices;
- X char fig_name[PIC_NAME_LIMIT];
- X double label_width;
- X edge_list *e_list;
- X struct pict *next_pic;
- X} picture;
- X
- typedef struct plist_entry {
- X int pic_limit;
- X int pics_in_list;
- X double total_label_width;
- X char pic_title[PIC_TITLE_LIMIT];
- X picture *pic;
- X} picture_list;
- X
- X
- extern char *malloc();
- extern char *calloc();
- extern char *index();
- END_OF_FILE
- if test 949 -ne `wc -c <'cpic/cpic.h'`; then
- echo shar: \"'cpic/cpic.h'\" unpacked with wrong size!
- fi
- # end of 'cpic/cpic.h'
- fi
- echo shar: End of archive 1 \(of 1\).
- cp /dev/null ark1isdone
- MISSING=""
- for I in 1 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have the archive.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-
-